/*
 * PhotonRTOS础光实时操作系统 -- ActivateTask接口实现文件
 *
 * Copyright (C) 2022 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <autosar/internal.h>
#include <photon/timex.h>

VAR(struct smp_lock, TYPEDEF) activate_task_async_lock;
__attribute__((aligned(PROCESS_STACK_SIZE)))
VAR(union process_union, AUTOMATIC) osek_stacks[OS_NR_TASK] = {};

static VAR(int8_t, AUTOMATIC) flages2string[3][2] = {
	" ",
	"N",
	"Y",
};

static VAR(int8_t, AUTOMATIC) state_strings[6][8] = {
	"no",
	"ready",
	"running",
	"waiting",
	"suspend",
	"-------",
};

static VAR(int8_t, AUTOMATIC) app_mode2string[2][8] = {
	"default",
	"test",
};

static VAR(int8_t, AUTOMATIC) auto_start2string[2][2] = {
	"N",
	"Y",
};

VAR(uint64_t, AUTOMATIC) last_task_activate_time[MAX_CPUS];

FUNC(void, OS_CODE) osek_init_task(
	VAR(TaskType, AUTOMATIC)TaskID)
{
	sched_init_task(TaskID);
}

/**
 * 激活任务，从初始地方重新执行
 */
FUNC(void, OS_CODE) osek_activate_task(
	VAR(TaskType, AUTOMATIC) task_id)
{
	sched_activate_task(task_id);
}


FUNC(void, OS_CODE) osek_deactivate_task(
	VAR(TaskType, AUTOMATIC) task_id)
{
	sched_deactivate_task(task_id);
}

FUNC(void, OS_CODE) osek_task_change_prio(
	VAR(TaskType, AUTOMATIC) task_id,
	VAR(int32_t, AUTOMATIC) prio)
{
	sched_task_change_prio(task_id, prio);
}

FUNC(void, OS_CODE) osek_yield(void)
{
	sched_yield();
}

FUNC(void, OS_CODE) osek_task_wakeup(
	VAR(TaskType, AUTOMATIC) task_id)
{
#ifdef AUTOSAR_TIMING_PROTECTION
	uint64_t activate_time = percpu_last_task_activate_time;
	/**
	 * [SWS_Os_00465] [OS Module应该保证两次任务激活的间隔时间在OsTaskTimeFrame以上]
	 * (1)percpu_last_task_activate_time == -1 表示第一次被激活。
	 * (2)两次激活时间超过了autosar_time_frame的规定值.(微秒为单位)
	 * 以上两种情况可以正常激活，否则就触发 时间保护钩子
	*/
	if (time_protect_disable == 0 && activate_time != 0 &&
		osek_tasks[task_id].cp_attr.cp_task_time_frame  >
		cycles_to_usecs(get_cycles()) - activate_time) {
		autosar_protect_hook(E_OS_PROTECTION_ARRIVAL);
	}
	/**
	 * [SWS_Os_00469] [当任务被激活时OsTaskTimeFrame应该开始计数]
	*/
	percpu_last_task_activate_time = cycles_to_usecs(get_cycles());
#endif
	sched_task_wakeup(task_id);
}

LOCAL_INLINE FUNC(int32_t, OS_CODE) act_count_valid(
	VAR(int32_t, AUTOMATIC) TaskID)
{
	P2VAR(struct task_desc, AUTOMATIC, OS_APPL_DATA) osk = &osek_tasks[TaskID];

	if (osk->activate_count < osk->max_activate_count) {
		return 1;
	}

	return 0;
}

FUNC(StatusType, OS_CODE) __osek_activate_task(
	VAR(TaskType, AUTOMATIC) TaskID)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;
	/**
	 * 总是可以激活挂起状态的任务
	 * 而不必考虑它是基本任务还是扩展任务
	 */
	if (osek_tasks[TaskID].state == SUSPENDED) {
		/**
		 * 递增激活次数
		 */
		osek_tasks[TaskID].activate_count++;
		/**
		 * 先清空事件掩码再唤醒，避免错误的发送事件给任务
		 */
		osek_tasks[TaskID].event_mask = 0;
		osek_tasks[TaskID].event_wait = 0;

		osek_activate_task(TaskID);

	} else if (osek_tasks[TaskID].flags	& TF_EXTENDED) {
		/* 未挂起的扩展任务 */
		ret = E_OS_LIMIT;
	} else { /* 基本任务，可以多次激活 */
		/**
		 * 激活次数未超过最大值
		 */
		if (act_count_valid(TaskID)) {

			/**
			 * 递增激活次数
			 */
			osek_tasks[TaskID].activate_count++;
			/**
			 * 对于基本任务来说，没有相关事件，因此不必清空其事件掩码
			 */
			osek_activate_task(TaskID);
		} else { /* 重复激活次数过多，返回E_OS_LIMIT */
			ret = E_OS_LIMIT;
		}
	}
	return ret;
}

/**
 * 将任务<TaskID>从挂起状态转换为就绪状态。
 * 操作系统确保任务代码从其第一行开始执行。
 *  语法：
 *      StatusType ActivateTask ( TaskType <TaskID> )
 *  参数（输入）：
 *      TaskID	任务引用
 * 参数（输出）：
 *      无
 *  特殊说明：
 *      该服务可能从中断级或者任务级被调用。
 *		在ActivateTask调用后，
 *		重调度依赖于它被调用的位置
 *		（ISR、不可抢占任务、可抢占任务）。
 *      如果E_OS_LIMIT被返回，激活操作被忽略。
 *      当一个扩展任务从挂起状态转换到就绪状态时，
 *		它的所有事件被清除。
 * 状态：
 *      标准：
 *          无错误，E_OK
 *          太多任务被激活，E_OS_LIMIT
 *      扩展：
 *          任务<TaskID>无效，E_OS_ID
 *  一致性：
 *      BCC1, BCC2, ECC1, ECC2
 */
FUNC(StatusType, OS_CODE) ActivateTask(
	VAR(TaskType, AUTOMATIC) TaskID)
{
#ifdef AUTOSAR_TIMING_PROTECTION
	uint64_t activate_time;
#endif
	VAR(StatusType, AUTOMATIC) ret = E_OK;
#if defined(AUTOSAR_OS_APPLICATION)
	VAR(ApplicationType, AUTOMATIC) app_id;
	VAR(ApplicationType, AUTOMATIC) trusted_func_app_id;
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) pro_desc = current_proc_info();
	P2VAR(struct process_desc, AUTOMATIC, OS_APPL_DATA) target_pro_desc
		= osek_tasks[TaskID].stack;
	trusted_func_app_id = pro_desc->object.trusted_func_app_id;
	app_id = trusted_func_app_id != INVALID_OSAPPLICATION
		? trusted_func_app_id : GetApplicationID();
#endif /* defined(AUTOSAR_OS_APPLICATION) */

#if defined(EXTENDED_STATUS)
	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 */
	if (osek_tasks[TaskID].stack == NULL || TaskID >=OS_NR_TASK || osek_tasks[TaskID].core_id != smp_processor_id()) {
		/**
		 * 根据OSEK规范，当ID过大时，返回E_OS_ID
		 * 注意这里TaskType为无符号数
		 */
		ret = E_OS_ID;
		goto out;
	}
	/**
	 * 在扩展模式下，检查是否有权访问app_id。
	 */
#if defined(AUTOSAR_OS_APPLICATION)
	if (current->is_autosar_task == 1 && CheckObjectAccess(app_id, TYPE_TASK, &target_pro_desc->object) != ACCESS) {
		ret = E_OS_ID;
		goto out;
	}
#endif /* defined(AUTOSAR_OS_APPLICATION) */
#endif

#ifdef AUTOSAR_TIMING_PROTECTION
	activate_time = percpu_last_task_activate_time;
	/**
	 * [SWS_Os_00465] [OS Module应该保证两次任务激活的间隔时间在OsTaskTimeFrame以上]
	 * (1)percpu_last_task_activate_time == 0 表示第一次被激活。
	 * (2)两次激活时间超过了autosar_time_frame的规定值.(微秒为单位)
	 * 以上两种情况可以正常激活，否则就触发 时间保护钩子
	*/
	if (time_protect_disable == 0 && activate_time != 0 &&
		osek_tasks[TaskID].cp_attr.cp_task_time_frame + activate_time >
		(cycles_to_usecs(get_cycles()))) {
		pr_err("ProtectionHook E_OS_PROTECTION_ARRIVAL\n");
		autosar_protect_hook(E_OS_PROTECTION_ARRIVAL);
	}
	/**
	 * [SWS_Os_00469] [当任务被激活时OsTaskTimeFrame应该开始计数]
	*/
	percpu_last_task_activate_time = cycles_to_usecs(get_cycles());
#endif
	SuspendAllInterrupts();

	ret = __osek_activate_task(TaskID);
	/**
	 * 注意，这里可能有重调度
	 */
	ResumeAllInterrupts();

out:
	/**
	 * 如果出现错误，就调用错误钩子
	 * 如果没有配置错误钩子宏，
	 * 编译器会做优化，不用担心。
	 */
	if (ret != E_OK){
		osek_call_hook_1(ActivateTask, ret, TaskID);
	}

	return ret;
}

#if defined(AUTOSAR_OS_APPLICATION)
/*
 * 语法
 * void ActivateTaskAsyn (
 *      TaskType id
 * )
 *
 * 服务 ID [hex]
 *      0x33
 *
 * 同步/异步
 *      异步（Asynchronous ）
 *
 * 可重入性
 *      可重入
 *
 * 参数 (in)
 *      id
 *      待激活任务的id
 *
 * 参数 (inout)
 *      None
 *
 * 参数 (out)
 *      None
 *
 * 返回值
 *      None
 *
 * 描述
 *      ActivateTask() 函数的异步版本。旨在用于跨核心任务激活。可能的错误
 * 不会返回给调用者，但可能会通过错误钩子报告。
 *
 * 引用
 *      AUTOSAR OS 8.4.38 ActivateTaskAsyn [SWS_Os_91022]
 */
FUNC(void, OS_CODE) ActivateTaskAsyn(
		VAR(TaskType, AUTOMATIC) id)
{
	VAR(uintptr_t, AUTOMATIC) flag;
	VAR(int32_t, AUTOMATIC) i;
	VAR(cpumask_t, AUTOMATIC) ipi_mask;

	CONTEXT_CHECK_NO_RETURN_VAL(ENV_TASK | ENV_CAT2_ISR)

	smp_lock_irqsave(&activate_task_async_lock, flag);

	/**
	 * 设置标志，表示当前任务需要被异步激活
	*/
	set_task_activate_async_flag(&osek_tasks[id]);
	/**
	 * 设置标志，表示当前核上有任务等待被异步激活。
	*/
	set_core_need_activate(osek_tasks[id].core_id);
	osek_tasks[id].cp_attr.async_activate_caller[current->osek_id] = 1;

	smp_unlock_irqrestore(&activate_task_async_lock, flag);
	
	for (i = 0; i < MAX_CPUS; i++)
		cpumask_clear_cpu(i, &ipi_mask);

	cpumask_set_cpu(osek_tasks[id].core_id, &ipi_mask);

	arch_raise_ipi(&ipi_mask, IPI_ASYNC);
}
#endif /* defined(AUTOSAR_OS_APPLICATION) */

static inline int32_t act_count_invalid(int32_t TaskID)
{
	struct task_desc *osk = &osek_tasks[TaskID];

	if (osk->activate_count >= osk->max_activate_count) {
		return 1;
	}

	return 0;
}

static inline int32_t prio_is_MAX(int32_t TaskID)
{
	struct task_desc *osk = &osek_tasks[TaskID];

	if (osk->sched_prio == TASK_MAX_PRIORITY) {
		return 1;
	}

	return 0;
}

static void __osek_chain_task(TaskType TaskID)
{
	osek_tasks[osek_current_id()].sched_prio =
				osek_tasks[osek_current_id()].prio;
	osek_tasks[osek_current_id()].activate_count--;
	ASSERT(osek_tasks[osek_current_id()].activate_count >= 0);

	/**
	 * 基本任务可以被激活多次，如果当前任务是基本任务，并且激活次数不为0
	 * 就不能将其挂起
	 */
	if (osek_tasks[osek_current_id()].activate_count == 0) {
		osek_tasks[osek_current_id()].state = SUSPENDED;
		/**
		 * 从队列中摘除当前任务
		 */
		osek_deactivate_task(osek_current_id());
	} else {
		osek_tasks[osek_current_id()].state = READY;
		/**
		 * 在激活任务的时候，再清空事件和资源
		 */
		osek_activate_task(TaskID);
	}
	osek_tasks[TaskID].activate_count++;
	if (osek_tasks[TaskID].state == SUSPENDED) {
		/**
		 * 在激活任务的时候，再清空事件和资源
		 */
		osek_activate_task(TaskID);
	}
}

/**
 * 这个服务导致调用任务被终止。
 * 在调用任务被终止后，任务<TaskID>被激活。
 * 使用该服务，它确保在调用任务被终止后，
 * 后续任务开始在最初始地方运行。
 * 语法：
 *     StatusType ChainTask ( TaskType <TaskID> )
 * 参数（输入）：
 *     TaskID	 对随后将被激活任务的引用
 * 参数（输出）：
 *     无
 * 特殊说明：
 *     如果后续任务被标识为当前任务，
 *     它并不会导致多个请求。
 *     任务并不会转换为挂起状态，而是立即变成就绪状态。
 *     分配给调用任务的内部资源被自动释放，
 *     即使后续任务被标识为当前任务也是如此。
 *     其他由当前任务占据的资源必须在
 *     ChainTask被调用前释放。
 *     如果某个资源仍然被占据为标准状态，
 *     其行为是未定义的。
 *     如果调用成功，ChainTask并不会返回到调用者，
 *     其结果状态不能被评估。
 *     在错误时，服务返回到调用任务，并且提供一个状态，
 *     该状态可以被调用者判断。
 *     如果ChainTask调用成功，它会确保产生重调度。
 *     不调用TerminateTask或者ChainTask就结果一个任务函数，
 *     这是严格禁止的，并且可能将系统置于未定义状态。
 *     如果E_OS_LIMIT被返回，激活过程被忽略。
 *     当一个扩展任务从挂起状态转换为就绪状态，
 *     它的所有事件被清除。
 * 状态：
 *     标准：
 *          不返回到调用者
 *          太多任务被激活，E_OS_LIMIT
 *     扩展：
 *          任务<TaskID>无效，E_OS_ID
 *          调用任务占据资源，E_OS_RESOURE
 *          在中断级调用，E_OS_CALLEVEL
 * 一致性：
 *     BCC1, BCC2, ECC1, ECC2
 */
FUNC(StatusType, OS_CODE) ChainTask(
	VAR(TaskType, AUTOMATIC)TaskID)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;

#if defined(EXTENDED_STATUS)
	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)
	if (TaskID >=OS_NR_TASK) {
		/**
		 * 根据OSEK规范，当ID过大时，返回E_OS_ID
		 * 注意这里TaskType为无符号数
		 */
		ret = E_OS_ID;
		goto out;
	}

	if (!in_osek_task()) {
		/**
		 * 根据OSEK规范，当调用级别不正确时，返回E_OS_CALLEVEL
		 * 表示在非任务上下文中调用了此函数
		 */
		ret = E_OS_CALLEVEL;
		goto out;
	}

	if (OS_NR_RESOURCE > 0) { /* 系统资源数量不为0 */
		/**
		 * 任务即将退出，不应当持有资源
		 */
		if  (osek_tasks[osek_current_id()].resource_count != 0) {
			ret = E_OS_RESOURCE;
			goto out;
		}

		/**
		 * TASK_MAX_PRIORITY该优先级用于优先级上限协议
		 * 既然已经不持有资源，就不应该处于该优先级
		 */
		if (prio_is_MAX(osek_current_id())) {
			ret = E_OS_RESOURCE;
			goto out;
		}
	}
#endif

	/**
	 * 如果要激活的是当前任务
	 * 那么相当于重新执行任务，其激活次数不变
	 * 这种情况下不必检查激活次数
	 */
	if (TaskID != osek_current_id()) {
		/* 要激活的任务不是当前任务 */
		/**
		 * 激活次数过多
		 */
		if (act_count_invalid(TaskID)) {
			ret = E_OS_LIMIT;
			goto out;
		}
	}

#if defined(CONFIG_OSEK_HOOK_POST_SCHEDULE)
	CONTEXT_MARK_START(ENV_POSTTASK_HOOK)
	PostTaskHook();
	CONTEXT_MARK_END
#endif

	SuspendAllInterrupts();
	/**
	 * 这里真正执行切换操作
	 */
	__osek_chain_task(TaskID);
	/**
	 * 注意，这里可能有重调度
	 */
	ResumeAllInterrupts();
	/**
	 * 不应当运行到这里来，不过还是强制调度一下
	 * 注意schedule不是OSEK接口
	 */
	schedule();
	/**
	 * 更不应当运行到这里
	 */
	BUG();

out:
	/**
	 * 如果出现错误，就调用错误钩子
	 * 如果没有配置错误钩子宏，
	 * 编译器会做优化，不用担心。
	 */
	if (ret != E_OK) {
		osek_call_hook_1(ChainTask, ret, TaskID);
	}

	return ret;
}

/**
 * 返回当前正在运行任务的TaskID信息。
 * 语法：
 *     StatusType GetTaskID ( TaskRefType <TaskID> )
 * 参数（输入）：
 *     无
 * 参数（输出）：
 *     对当前正在运行任务的引用
 * 特殊说明：
 *     允许在任务级、ISR级以及内部钩子例程调用。
 *     该服务目的是用在库函数和钩子例程中。
 *     如果<TaskID>不能被计算(没有任务在运行)，
 *     服务返回INVALID_TASK作为TaskType。
 * 状态：
 *     标准：
 *        没有错误，E_OK
 *     扩展：
 *        没有错误，E_OK
 * 一致性：
 *     BCC1, BCC2, ECC1, ECC2
 */
FUNC(StatusType, OS_CODE) GetTaskID(
	VAR(TaskRefType, AUTOMATIC) TaskID)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;

	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK \
	| ENV_PRETASK_HOOK | ENV_POSTTASK_HOOK | ENV_PROTECTION_HOOK)

	*TaskID = osek_current_id();

	return ret;
}



/**
 * 如果一个高优先级任务就绪
 * 任务的内部资源将被释放，当前任务进入就绪状态
 * 其上下文将被保存，并且高优先级任务被执行。
 * 否则调用任务继续运行。
 * 语法：
 *     StatusType Schedule ( void )
 * 参数（输入）：
 *     无
 * 参数（输出）：
 *     无
 * 特殊说明：
 *     只有在系统生成期间将内部资源分配给调用任务时，
 *     才会发生重新调度。
 *     对这些任务，Schedule允许处理器分配给
 *     另外一个内部资源上限优先级相同或者更低任务，
 *     并且比应用特定优先级更高。
 *     当从Schedule返回时，内部资源被重新获取。
 *     在没有分配内部资源（可抢占任务），
 *     该服务对任务没有影响。
 * 状态：
 *     标准：
 *        没有错误，E_OK
 *     扩展：
 *        在中断级别调用，E_OS_CALLEVEL
 *        调用任务占据资源，E_OS_RESOURE
 * 一致性：
 *     BCC1, BCC2, ECC1, ECC2
 */
FUNC(StatusType, OS_CODE) Schedule(void)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;
	
#if defined(EXTENDED_STATUS)
	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)
#endif

	osek_yield();

	return ret;
}

/**
 * 返回在调用GetTaskState时，任务（运行、就绪、等待、挂起）状态。
 * 语法：
 *     StatusType GetTaskState ( TaskType <TaskID>, TaskStateRefType <State> )
 * 参数（输入）：
 *     TaskID	任务引用
 * 参数（输出）：
 *     State	对任务<TaskID>状态的引用
 * 特殊说明：
 *     允许在中断服务程序、任务级、
 *     以及某些钩子例程中调用该服务。
 *     当在全抢占系统任务中调用时，
 *     在判断结果的时候，其结果可能已经不正确。
 *     当针对任务调用该服务，而任务被激活不止一次，
 *     并且如果任务的某个实例正在运行，
 *     则结果状态被设置为运行状态。
 * 状态：
 *     标准：
 *        没有错误，E_OK
 *     扩展：
 *        任务<TaskID>无效，E_OS_ID
 * 一致性：
 *     BCC1, BCC2, ECC1, ECC2
 */
FUNC(StatusType, OS_CODE) GetTaskState(
	VAR(TaskType, AUTOMATIC) TaskID,
	VAR(TaskStateRefType, AUTOMATIC) State)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;
	
#if defined(EXTENDED_STATUS)
	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR | ENV_ERROR_HOOK \
			| ENV_PRETASK_HOOK | ENV_POSTTASK_HOOK)
	/**
	 * 在扩展模式下，检查传入参数是否过大
	 */
	if (TaskID >=OS_NR_TASK) {
		/**
		 * 根据OSEK规范，当ID过大时，返回E_OS_ID
		 * 注意这里TaskType为无符号数
		 */
		ret = E_OS_ID;
		goto out;
	}
#endif

	*State = (TaskStateType) osek_tasks[TaskID].state;

out:
	/**
	 * 如果出现错误，就调用错误钩子
	 * 如果没有配置错误钩子宏，
	 * 编译器会做优化，不用担心。
	 */
	if (ret != E_OK) {
		osek_call_hook_2(GetTaskState, ret, TaskID, State);
	}

	return ret;
}

#if defined(AUTOSAR_SHOW_TASK_INFO)
struct task_info all_task_info[OS_NR_TASK] = {};

/**
 * 存储显示任务信息时的顺序
 * osek_tasks[sorted_task[i]]即为第i个该显示的任务
 */
uintptr_t sorted_task[OS_NR_TASK];

/**
 * 判断显示任务信息时两个任务谁在前面
 * 如果 a 在前面返回真
 */
static inline bool task_above(uintptr_t a, uintptr_t b)
{
	bool ret = false;

	if (osek_tasks[a].core_id < osek_tasks[b].core_id) {
		ret = true;
	} else if (osek_tasks[a].core_id > osek_tasks[b].core_id) {
		ret = false;
	} else if (osek_tasks[a].app_id < osek_tasks[b].app_id) {
		ret = true;
	} else if (osek_tasks[a].app_id > osek_tasks[b].app_id) {
		ret = false;
	/**
	 * 不必再判断 task_id,
	 * 因为任务已预先按照task_id排序,
	 * 插入排序是稳定排序,
	 * 前面的信息一致
	 * 则task_above(sorted_task[j], sorted_task[j - 1])一定为假
	 */
	} else {
		ret = false;
	}

	return ret;
}

/* 根据核ID,应用ID,任务ID排序 */
static void sort_task(uintptr_t task_num)
{
	uintptr_t i, j, tmp;

	/* 初始化排序队列 */
	for (i = 0; i < task_num; i++) {
		sorted_task[i] = i;
	}

	if (task_num < 2) {
		return;
	}

	/**
	 * 插入排序法
	 * 在任务已按照核ID，应用ID排序时代价最小
	 * 基本符合顺序时代价不大
	 */
	for (i = 1; i < task_num; i++) {
		for (j = i; j >= 1; j--) {
			if (task_above(sorted_task[j], sorted_task[j - 1])) {
				tmp = sorted_task[j];
				sorted_task[j] = sorted_task[j - 1];
				sorted_task[j - 1] = tmp;
			} else {
				break;
			}
		}
	}
}

/* 更新任务静态信息缓冲区 */
static void update_task_static_info(uintptr_t task_num)
{
	uintptr_t i;

	for (i = 0; i < task_num; i++) {
		all_task_info[i].core_id = osek_tasks[i].core_id;
		all_task_info[i].app_id = osek_tasks[i].app_id;
		all_task_info[i].osek_id = osek_tasks[i].osek_id;

		all_task_info[i].prio = osek_tasks[i].prio;
		all_task_info[i].stack_size = osek_tasks[i].stack_size;
		all_task_info[i].execution_budget = osek_tasks[i].cp_attr.cp_task_execution_budget;

		all_task_info[i].flags = osek_tasks[i].flags;
		all_task_info[i].max_activate_count = osek_tasks[i].max_activate_count;
		all_task_info[i].app_mode = osek_tasks[i].app_mode;
		all_task_info[i].auto_start = osek_tasks[i].auto_start;
	}
}

/* 更新任务基本信息缓冲区 */
static void update_task_base_info(uintptr_t start, uintptr_t end)
{
	uint8_t *ptr, *stack_end;
	uintptr_t i;

	for (i = start; i < end; i++) {
		all_task_info[i].state = osek_tasks[i].state;
		all_task_info[i].sched_prio = osek_tasks[i].sched_prio;
	
		all_task_info[i].curr_run_time = osek_tasks[i].cp_attr.cp_task_execution_time;
		if (all_task_info[i].state == RUNNING) {
			all_task_info[i].all_run_time = jiffies_to_msecs((uint32_t)get_jiffies_64() - (uint32_t)osek_tasks[i].jiffies64);
#if defined(AUTOSAR_TIMING_PROTECTION)
			all_task_info[i].curr_run_time += (cycles_to_usecs(get_cycles()) - osek_tasks[i].cp_attr.cp_task_start_point);
#endif
		} else {
			all_task_info[i].all_run_time = jiffies_to_msecs((uint32_t)osek_tasks[i].jiffies64);
		}

		stack_end = (uint8_t *)osek_tasks[i].stack + all_task_info[i].stack_size;
		ptr = (uint8_t *)osek_tasks[i].stack + sizeof(struct process_desc);
		for (; ptr < stack_end; ptr++) {
			if (*ptr != '#') {
				break;
			}
		}
		all_task_info[i].stack_used = 100U * (stack_end - ptr + (uint8_t)sizeof(struct process_desc)) / all_task_info[i].stack_size;
	}
}

/* 更新任务拓展信息缓冲区 */
static void update_task_ext_info(uintptr_t start, uintptr_t end)
{
	uintptr_t i;

	for (i = start; i < end; i++) {
		all_task_info[i].activate_count = osek_tasks[i].activate_count;
		all_task_info[i].resource_count = osek_tasks[i].resource_count;
		all_task_info[i].resource_mask = osek_tasks[i].resource_mask;
		all_task_info[i].event_mask = osek_tasks[i].event_mask;
		all_task_info[i].event_wait = osek_tasks[i].event_wait;
	}
}

/**
 * 更新任务信息缓冲区
 * base:    BASE_INFO(基本信息)，EXT_INFO(拓展信息)
 * osek_id: ALL_TASK(所有任务)，0,1,2...
 * 
 * 更新所有任务信息时，返回更新的任务数
 * 更新指定任务信息时，返回osek_id表示更新失败，返回osek+1表示更新成功
 */
FUNC(uintptr_t, OS_CODE) update_task_info(
	VAR(uint32_t, AUTOMATIC) base,
	VAR(uintptr_t, AUTOMATIC) osek_id)
{
	VAR(uintptr_t, AUTOMATIC) start, end = osek_id;
	static VAR(uintptr_t,AUTOMATIC) task_num = 0;

	/* 系统启动后第一次调用此函数 */
	if (task_num == 0){
		/* 计算已初始化的任务数量 */
		for (start = 0; start < (uintptr_t)OS_NR_TASK; start++) {
			if (osek_tasks[start].flags == 0U) {
				break;
			}
		}
		task_num = start;
		/* 更新静态的任务信息并排序,系统启动只更新一次 */
		update_task_static_info(task_num);
		sort_task(task_num);
	}

	/* 计算需要更新的任务范围 */
	if (osek_id == ALL_TASK) {
		start = 0;
		end = task_num;
	} else if (osek_id >= (uintptr_t)OS_NR_TASK) {
		start = end;
	} else {
		start = osek_id;
		if (osek_tasks[end].flags != 0U) {
			end++;
		}
	}

	/* 更新任务信息缓冲区 */
	if (start < end) {
		if (base >= BASE_INFO) {
			update_task_base_info(start, end);
		} else {
			update_task_ext_info(start, end);
		}
	}

	return end;
}

/* 任务状态转字符串 */
static FUNC_P2VAR(int8_t, OS_CODE, AUTOMATIC) state2string_fun(
	VAR(uintptr_t, AUTOMATIC) state)
{
	P2VAR(int8_t, AUTOMATIC, OS_APPL_DATA) str = NULL;

	switch (state)
	{
	case (uintptr_t)0:
		str = state_strings[0];
	case READY:
		str = state_strings[1];
		break;
	case RUNNING:
		str = state_strings[2];
		break;
	case WAITING:
		str = state_strings[3];
		break;
	case SUSPENDED:
		str = state_strings[4];
		break;
	default:
		str = state_strings[5];
		break;
	}

	return str;
}

/* 输出任务信息的标题及系统开机时间 */
static FUNC(void, AUTOMATIC) print_task_info_title(uint32_t base)
{
	VAR(uint32_t, AUTOMATIC) h, m, s, sys_run_time = \
			(uint32_t)jiffies_to_msecs((uintptr_t)get_jiffies_64()) / 1000U;
	VAR(int8_t, AUTOMATIC) base_ext[2][7] = {
		"拓展",
		"基本",
	};

	/* 计算已开机时间 */
	h = sys_run_time / 3600U;
	sys_run_time = sys_run_time % 3600U;
	m = sys_run_time / 60U;
	s = sys_run_time % 60U;

	/* 输出标题和已开机时间 */
	if (base <= 1U) {
		if (h == 0U) {
			if (m == 0U) {
				printk("任务%s信息（系统已运行： %d 秒）\n", base_ext[base], s);
			} else {
				printk("任务%s信息（系统已运行： %2d 分钟 %02d 秒）\n", base_ext[base], m, s);
			}
		} else {
			printk("任务%s信息（系统已运行： %d 小时 %02d 分钟 %02d 秒）\n", base_ext[base], h, m, s);
		}
	}
}

/* 从缓存区输出任务的基本信息 */
static FUNC(void, AUTOMATIC) print_task_base_info(
	VAR(uintptr_t, AUTOMATIC) start,
	VAR(uintptr_t, AUTOMATIC) end)
{
	VAR(uintptr_t, AUTOMATIC) i;
	VAR(int8_t, AUTOMATIC) interval_head = ' ';
	VAR(int8_t, AUTOMATIC) interval_content = ' ';
	P2VAR(struct task_info, AUTOMATIC, OS_APPL_DATA) task = NULL;
	VAR(int32_t, AUTOMATIC) core_id = INVALID_CORE_ID;
	VAR(uint32_t, AUTOMATIC) app_id = INVALID_APP_ID;


	for (i = start; i < end; i++) {
		/* 是否按顺序输出 */
		if ((end - start) > 1) {
			task = &(all_task_info[sorted_task[i]]);
		} else {
			task = &(all_task_info[i]);
		}
		/* 是否和上一任务的核ID一致 */
		if (core_id != task->core_id) {
			app_id = INVALID_APP_ID;
			printk("core_id: %d\n", task->core_id);
			core_id = task->core_id;
		}
		/* 是否和上一任务的应用ID一致 */
		if (app_id != task->app_id) {
			printk("    app_id: %d\n", task->app_id);
			app_id = task->app_id;
			/* 输出任务基本信息属性名 */
			printk("        %4s%c%7s%c%17s%c%9s%c%5s%c%7s%c%4s%c\n",
				"ID", interval_head,
				"state", interval_head,
				"curr_run_time(us)", interval_head,
				"time(ms)", interval_head,
				"prio", interval_head,
				"stack", interval_head,
				"used", interval_head);
		}

		/* 输出任务基本信息 */
		printk("        %4d%c%7s%c%8d/%8d%c%9d%c%2d/%2d%c%#7x%c%3d%%%c\n",
			task->osek_id, interval_content,
			state2string_fun(task->state), interval_content,
			task->curr_run_time, task->execution_budget, interval_content,
			task->all_run_time, interval_content,
			task->sched_prio, task->prio, interval_content,
			task->stack_size, interval_content,
			task->stack_used, interval_content);
	}
}

/* 从缓存区输出任务的拓展信息 */
static FUNC(void, OS_CODE) print_task_ext_info(
	VAR(uintptr_t, AUTOMATIC) start,
	VAR(uintptr_t, AUTOMATIC) end)
{
	VAR(uintptr_t, AUTOMATIC) i;
	VAR(int8_t, AUTOMATIC) interval_head = ' ';
	VAR(int8_t, AUTOMATIC) interval_content = ' ';
	P2VAR(struct task_info, AUTOMATIC, OS_APPL_DATA) task = NULL;
	VAR(int32_t, AUTOMATIC) core_id = INVALID_CORE_ID;
	VAR(uint32_t, AUTOMATIC) app_id = INVALID_APP_ID;

	for (i = start; i < end; i++) {
		/* 是否按顺序输出 */
		if ((end - start) > 1) {
			task = &(all_task_info[sorted_task[i]]);
		} else {
			task = &(all_task_info[i]);
		}
		/* 是否和上一任务的核ID一致 */
		if (core_id != task->core_id) {
			app_id = INVALID_APP_ID;
			printk("core_id: %d\n", task->core_id);
			core_id = task->core_id;
		}
		/* 是否和上一任务的应用ID一致 */
		if (app_id != task->app_id) {
			printk("    app_id: %d\n", task->app_id);
			app_id = task->app_id;
			/* 输出任务拓展信息属性名 */
			printk("        %4s%c%3s%c%6s%c%8s%c%13s%c%10s%c%10s%c%8s%c%10s%c\n",
				"ID", interval_head,
				"ext", interval_head,
				"active", interval_head,
				"resource", interval_head,
				"resource_mask", interval_head,
				"event_mask", interval_head,
				"event_wait", interval_head,
				"app_mode", interval_head,
				"auto_start", interval_head);
		}
		/* 输出任务拓展信息 */
		printk("        %4d%c%3s%c%3d/%2d%c%8d%c       %#06x%c    %#06x%c    %#06x%c%8s%c%10s%c\n",
			task->osek_id, interval_content,
			flages2string[task->flags], interval_content,
			task->activate_count, task->max_activate_count, interval_content,
			task->resource_count, interval_content,
			task->resource_mask, interval_content,
			task->event_mask, interval_content,
			task->event_wait, interval_content,
			app_mode2string[task->app_mode], interval_content,
			auto_start2string[task->auto_start], interval_content);
	}
}

/**
 * 显示任务信息
 * base:    BASE_INFO(基本信息)，EXT_INFO(拓展信息)
 * osek_id: ALL_TASK(所有任务)，0,1,2...
 * 
 * 显示所有任务信息时，返回显示的任务数
 * 显示指定任务信息时，返回osek_id表示显示失败，返回osek+1表示显示成功
 */
FUNC(uintptr_t, OS_CODE) ShowTaskInfo(
	VAR(uint32_t, AUTOMATIC) base,
	VAR(uintptr_t, AUTOMATIC) osek_id)
{
	VAR(uintptr_t, AUTOMATIC) start, end = update_task_info(base, osek_id);

	/* 计算显示任务的范围 */
	if (osek_id == ALL_TASK) {
		start = 0;
	} else {
		start = osek_id;
	}

	if (start < end) {
		print_task_info_title(base);
		if (base >= BASE_INFO) {
			print_task_base_info(start, end);
		} else {
			print_task_ext_info(start, end);
		}
	}

	return end;
}

FUNC(void, OS_CODE) ShowAllTaskInfo(void)
{
	ShowTaskInfo(BASE_INFO, ALL_TASK);
	ShowTaskInfo(EXT_INFO, ALL_TASK);
}

#endif /* defined(AUTOSAR_SHOW_TASK_INFO) */

LOCAL_INLINE FUNC(int32_t, OS_CODE) task_prio_is_max(
	VAR(int32_t, AUTOMATIC) i)
{
	if (osek_tasks[i].sched_prio == TASK_MAX_PRIORITY) {
		return 1;
	}

	return 0;
}

static FUNC(void, OS_CODE) __osek_terminate_task(void)
{
	osek_tasks[osek_current_id()].sched_prio =
			osek_tasks[osek_current_id()].prio;
	osek_tasks[osek_current_id()].activate_count--;
	ASSERT(osek_tasks[osek_current_id()].activate_count >= 0);

	/**
	 * 基本任务可以被激活多次，如果当前任务是基本任务，并且激活次数不为0
	 * 就先退出，由系统守护任务将其激活
	 */
	osek_tasks[osek_current_id()].state = SUSPENDED;
	osek_deactivate_task(osek_current_id());
}

/**
 * 该服务导致调用任务被终止。
 * 调用任务从运行状态转换为挂起状态。
 * 语法：
 *     StatusType TerminateTask ( void )
 * 参数（输入）：
 *     无
 * 参数（输出）：
 *     无
 * 特殊说明：
 *     分配给调用任务的内部资源被自动释放。
 *     被任务占据的其他资源应当在
 *     调用TerminateTask之前被释放。
 *     如果某个资源仍然被占据为标准状态，
 *     那么其行为是未定义的。
 *     如果调用成功，TerminateTask不再返回到调用者，
 *     并且不能评估返回状态。
 *     如果扩展状态被使用，在错误情况下服务会返回，
 *     并且提供一个状态，该状态可以被应用所评估。
 *     如果TerminateTask服务被调用成功，它会确保产生重调度。
 *     不调用TerminateTask或者ChainTask而结束一个任务，
 *     这是严格禁止的，并且可能会将系统置于未定义状态。
 * 状态：
 *     标准：
 *        不返回到调用者
 * 扩展：
 *        任务仍然占据资源，E_OS_RESOURE
 *        在中断级调用，E_OS_CALLEVEL
 * 一致性：
 *     BCC1, BCC2, ECC1, ECC2
 */
FUNC(StatusType, OS_CODE)TerminateTask(void)
{
	VAR(StatusType, AUTOMATIC) ret = E_OK;

#if defined(EXTENDED_STATUS)
	CONTEXT_CHECK(ENV_TASK | ENV_CAT2_ISR)
	if (!in_osek_task()) {
		/**
		 * 根据OSEK规范，当调用级别不正确时，返回E_OS_CALLEVEL
		 * 表示在非任务上下文中调用了此函数
		 */
		ret = E_OS_CALLEVEL;
		goto out;
	}

	if (OS_NR_RESOURCE > 0) { /* 系统资源数量不为0 */
		/**
		 * 任务即将退出，不应当持有资源
		 */
		if (osek_tasks[osek_current_id()].resource_count != 0) {
			ret = E_OS_RESOURCE;
			goto out;
		}

		/**
		 * TASK_MAX_PRIORITY该优先级用于优先级上限协议
		 * 既然已经不持有资源，就不应该处于该优先级
		 */
		if (task_prio_is_max(osek_current_id())) {
			ret = E_OS_RESOURCE;
			goto out;
		}
	}

#endif

#if defined(CONFIG_OSEK_HOOK_POST_SCHEDULE)
	CONTEXT_MARK_START(ENV_POSTTASK_HOOK)
	PostTaskHook();
	CONTEXT_MARK_END
#endif

	SuspendAllInterrupts();
	/**
	 * 这里真正执行切换操作
	 */
	__osek_terminate_task();
	/**
	 * 注意，这里可能有重调度
	 */
	ResumeAllInterrupts();
	/**
	 * 不应当运行到这里来，不过还是强制调度一下
	 * 注意schedule不是OSEK接口
	 */
	schedule();
	/**
	 * 更不应当运行到这里
	 */
	BUG();

out:
	/**
	 * 如果出现错误，就调用错误钩子
	 * 如果没有配置错误钩子宏，
	 * 编译器会做优化，不用担心。
	 */
	if (ret != E_OK) {
		osek_call_hook_0(TerminateTask, ret);
	}

	return ret;
}

FUNC(void, OS_CODE) attrs_to_alarm(
	VAR(int32_t, AUTOMATIC) i)
{
	struct osek_alarm_attr *attr = osek_alarm_attrs[i];

	osek_alarms[i].callback = attr->callback;
	osek_alarms[i].counterID = attr->counterID;
	osek_alarms[i].waiter.callback = __osek_alarm_callback;
	osek_alarms[i].waiter.param = (void *)&(osek_alarms[i]);

}

FUNC(void, OS_CODE) attrs_to_task(
	VAR(int32_t, AUTOMATIC) i)
{
	P2VAR(union process_union, AUTOMATIC,OS_APPL_DATA) stack = &osek_stacks[i];
	VAR(int32_t, AUTOMATIC) j;

	memset(&osek_stacks[i], (int32_t)'#', sizeof(osek_stacks[i]));
	stack->process_desc.object.app_id = osek_task_attrs[i]->app_id;
	stack->process_desc.object.object_type = TYPE_TASK;
	for (j = 0; j < AUTOSAR_NR_APPLICATION; j++)
		stack->process_desc.object.accessable_application_id[j] = 1;

	osek_tasks[i].entry = osek_task_attrs[i]->entry;
	osek_tasks[i].flags = osek_task_attrs[i]->flags;
	osek_tasks[i].prio = osek_task_attrs[i]->prio;
	osek_tasks[i].app_mode = osek_task_attrs[i]->app_mode;
	osek_tasks[i].auto_start = osek_task_attrs[i]->auto_start;
	osek_tasks[i].core_id = osek_task_attrs[i]->core_id;
	osek_tasks[i].app_id = osek_task_attrs[i]->app_id;
	osek_tasks[i].is_autosar_task = 1;
	osek_tasks[i].cp_attr.cp_task_time_frame = osek_task_attrs[i]->cp_task_time_frame;
	osek_tasks[i].cp_attr.cp_isr_time_frame = osek_task_attrs[i]->cp_isr_time_frame;
	osek_tasks[i].cp_attr.cp_task_execution_budget =
		osek_task_attrs[i]->cp_task_execution_budget;
	osek_tasks[i].cp_attr.cp_isr_execution_budget = osek_task_attrs[i]->cp_isr_execution_budget;
	osek_tasks[i].cp_attr.prot_addr_start = 0x0;
	osek_tasks[i].cp_attr.prot_addr_end = 0xffffffff;
	osek_tasks[i].sched_policy = osek_task_attrs[i]->sched_policy;
}


/**
 * 所有任务的堆栈及描述符
 * 根据osek_task_attrs生成
 * 在StartOS函数中生成
 */
VAR(struct task_desc, AUTOMATIC) osek_tasks[OS_NR_TASK] = {};
